#ifndef DOWNLOADMANAGER_H
#define DOWNLOADMANAGER_H

// 约定：
// filePath 完整文件路径
// fileName 不带目录的文件名
// dir      目录路径
// name     不带扩展名和目录的文件名
// *注意，QFile 的习惯与此约定不同

#include <QObject>
#include <QPair>
#include <map>

class QNetworkAccessManager;
class QNetworkReply;
class QFile;

class YDDownloadManager : public QObject {
    Q_OBJECT
public:
    explicit YDDownloadManager(QObject *parent = 0);
    ~YDDownloadManager();

public slots:
    // localFileName 是指定的本地存储文件名
    // 如果 filePath 文件已经存在，那么在扩展名前加 _1，_2 等，依此类推
    // 如果 filePath 为空，则自定指定文件名
    // 如果自行指定文件名后发现同名的文件已经存在，则在扩展名前加 _1，_2 等，依此类推
    void startDownload(const QString& url, const QString& filePath, bool append);

    // 停止下载后连接资源被释放，本地的下载文件被保留，如果要继续下载，应开始一个新任务
    void stopDownload(const QString& url);

signals:
    void sigStarted(const QString& url);
    void sigStoped(const QString& url);
    // 如果出现了错误，则连接资源被自动释放，本地的下载文件被保留
    void sigErrorOccured(const QString& url, int code = 0);
    void sigFinished(const QString& url);
    void sigProgressChanged(const QString& url, qint64 bytesReceived, qint64 bytesTotal);
    void sigFileNameChanged(const QString& url, const QString& filePath);
    // 已经存在的下载如果再次调用下载，则触发信号
    void sigDuplicate(const QString& url);

private slots:
    void on_reply_error(int code);
    void on_reply_download_progress(qint64 bytesReceived, qint64 bytesTotal);
    void on_reply_finished();
    void on_reply_meta_data_changed();

private:
    typedef std::map<QString, QPair<QNetworkReply*, QFile*>> url_map_t;
    
    static QString fixFilePath(QFile* file);
    static QString getServerFileName(QNetworkReply* reply);

    void startDownload(const QString& url, QFile* file = nullptr);
    url_map_t::iterator findUrl(QNetworkReply* reply);
    
    QNetworkAccessManager* mgr;
    url_map_t urlMap;
};

#endif // DOWNLOADMANAGER_H
